package com.ruoyi.common.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.FSDirectory;

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.ExifThumbnailDirectory;
import com.ruoyi.project.system.picture.domain.Picture;

import net.semanticmetadata.lire.builders.DocumentBuilder;
import net.semanticmetadata.lire.builders.GlobalDocumentBuilder;
import net.semanticmetadata.lire.imageanalysis.features.global.ACCID;
import net.semanticmetadata.lire.imageanalysis.features.global.AutoColorCorrelogram;
import net.semanticmetadata.lire.imageanalysis.features.global.CEDD;
import net.semanticmetadata.lire.imageanalysis.features.global.COMO;
import net.semanticmetadata.lire.imageanalysis.features.global.ColorLayout;
import net.semanticmetadata.lire.imageanalysis.features.global.EdgeHistogram;
import net.semanticmetadata.lire.imageanalysis.features.global.FCTH;
import net.semanticmetadata.lire.imageanalysis.features.global.Gabor;
import net.semanticmetadata.lire.imageanalysis.features.global.JCD;
import net.semanticmetadata.lire.imageanalysis.features.global.LuminanceLayout;
import net.semanticmetadata.lire.imageanalysis.features.global.OpponentHistogram;
import net.semanticmetadata.lire.imageanalysis.features.global.PHOG;
import net.semanticmetadata.lire.imageanalysis.features.global.ScalableColor;
import net.semanticmetadata.lire.imageanalysis.features.global.SimpleColorHistogram;
import net.semanticmetadata.lire.imageanalysis.features.global.Tamura;
import net.semanticmetadata.lire.imageanalysis.features.global.joint.JointHistogram;
import net.semanticmetadata.lire.searchers.GenericFastImageSearcher;
import net.semanticmetadata.lire.searchers.ImageSearchHits;
import net.semanticmetadata.lire.searchers.ImageSearcher;
import net.semanticmetadata.lire.utils.ImageUtils;
import net.semanticmetadata.lire.utils.LuceneUtils;

public class LireUtil {
	public static int numResults = 9;
	public static String server = "http://localhost/";
	public static String indexPath ="C:\\Users\\Administrator\\Desktop\\index";
	public static boolean index(List<Picture> pictures) {
		/*
		 * 初始化builder 
		 * getGlobalDocumentBuilder()中加入了16中特征提取方式，将分别建立这16中特征的索引
		 */
		GlobalDocumentBuilder globalDocumentBuilder = getGlobalDocumentBuilder();
		
		/*
		 * 定义索引创建器 索引文件保存路径，true表示覆盖原有索引文件
		 */
		try {
			IndexWriter iw = LuceneUtils.createIndexWriter(indexPath, true);
			/*
			 * 迭代图片目录，使用GlobalDocumentBuilder创建特征，使用IndexWriter把特征加入到index
			 */
			for (Iterator<Picture> it = pictures.iterator(); it.hasNext();) {
				Picture picture = it.next();
				String imageFilePath = server+picture.getSrcPath();
				System.out.println("Indexing " + imageFilePath);
				try {
					BufferedImage img = ImageIO.read(new URL(imageFilePath));
					Document document = globalDocumentBuilder.createDocument(img,picture.getPictureId().toString());//id作为key建立索引
					iw.addDocument(document);
				} catch (Exception e) {
					System.err.println("Error reading image or indexing it.");
					e.printStackTrace();
				}
			}
			
			System.out.println("Finished indexing ...");
			
			/*
			 * 提交并关闭IndexWriter
			 */
			iw.commit();
			iw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	public static List<Long> search(String type,byte[] data) throws IOException{
		//使用IndexReader加载器索引文件
		IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));
		//把byte[]转换为InputStream
		InputStream in = new ByteArrayInputStream(data);
		//把InputStream转换为BufferedImage
		BufferedImage img = ImageIO.read(in);
		//为图片创建Document
		Document myDoc = getGlobalDocumentBuilder().createDocument(img, "searchImg");
		//获取指定类型的图片搜索器（CEDD等）
        ImageSearcher searcher = getSearcher(type);
        //使用图片搜索器在索引值对myDoc进行查找
        ImageSearchHits hits = searcher.search(myDoc, reader);
        //返回相似图片的id列表
        List<Long> ids = getPictures(hits, reader);
        //关闭IndexReader
        reader.close();
		return ids;
	}

	private static ImageSearcher getSearcher(String type) {
		ImageSearcher searcher=new GenericFastImageSearcher(numResults, CEDD.class);	
		switch(type) {
		case "CEDD":
			break;
		case "ACCID":
			searcher = new GenericFastImageSearcher(numResults, ACCID.class);
			break;
		case "ColorLayout":
			searcher = new GenericFastImageSearcher(numResults, ColorLayout.class);
			break;	
		case "FCTH":
			searcher = new GenericFastImageSearcher(numResults, FCTH.class);
			break;	
		case "JCD":
			searcher = new GenericFastImageSearcher(numResults, JCD.class);
			break;	
		case "EdgeHistogram":
			searcher = new GenericFastImageSearcher(numResults, EdgeHistogram.class);
			break;	
		case "ScalableColor":
			searcher = new GenericFastImageSearcher(numResults, ScalableColor.class);
			break;	
		case "AutoColorCorrelogram":
			searcher = new GenericFastImageSearcher(numResults, AutoColorCorrelogram.class);
			break;	
		case "Tamura":
			searcher = new GenericFastImageSearcher(numResults, Tamura.class);
			break;	
		case "Gabor":
			searcher = new GenericFastImageSearcher(numResults, Gabor.class);
			break;	
		case "SimpleColorHistogram":
			searcher = new GenericFastImageSearcher(numResults, SimpleColorHistogram.class);
			break;	
		case "OpponentHistogram":
			searcher = new GenericFastImageSearcher(numResults, OpponentHistogram.class);
			break;	
		case "JointHistogram":
			searcher = new GenericFastImageSearcher(numResults, JointHistogram.class);
			break;	
		case "LuminanceLayout":
			searcher = new GenericFastImageSearcher(numResults, LuminanceLayout.class);
			break;	
		case "PHOG":
			searcher = new GenericFastImageSearcher(numResults, PHOG.class);
			break;	
		case "COMO":
			searcher = new GenericFastImageSearcher(numResults, COMO.class);
			break;	
		} 
		return searcher;
	}
	
	private static GlobalDocumentBuilder getGlobalDocumentBuilder() {
		GlobalDocumentBuilder globalDocumentBuilder = new GlobalDocumentBuilder(CEDD.class);
        globalDocumentBuilder.addExtractor(ColorLayout.class);
        globalDocumentBuilder.addExtractor(FCTH.class);
        globalDocumentBuilder.addExtractor(JCD.class);
        globalDocumentBuilder.addExtractor(ScalableColor.class);
        globalDocumentBuilder.addExtractor(EdgeHistogram.class);
        globalDocumentBuilder.addExtractor(AutoColorCorrelogram.class);
        globalDocumentBuilder.addExtractor(Tamura.class);
        globalDocumentBuilder.addExtractor(Gabor.class);
        globalDocumentBuilder.addExtractor(SimpleColorHistogram.class);
        globalDocumentBuilder.addExtractor(OpponentHistogram.class);
        globalDocumentBuilder.addExtractor(JointHistogram.class);
        globalDocumentBuilder.addExtractor(LuminanceLayout.class);
        globalDocumentBuilder.addExtractor(PHOG.class);
        globalDocumentBuilder.addExtractor(ACCID.class);
        globalDocumentBuilder.addExtractor(COMO.class);
        return globalDocumentBuilder;
	}
	
	private static List<Long> getPictures(ImageSearchHits hits,IndexReader reader) {
		 List<Long> ids = new ArrayList<Long>();
	        for (int i = 0; i < hits.length(); i++) {
	            try {
	                String idstr = reader.document(hits.documentID(i)).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue();
	                System.out.println("result:"+idstr);
	                ids.add(Long.valueOf(idstr));
	            } catch (Exception ex) {
	                Logger.getLogger("global").log(Level.SEVERE, null, ex);
	            }
	        }
			return ids;
	    }
}
